﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Xml.Serialization;
using Ant.ICommon.Utilities;

namespace Ant.Interface.Mef.Model.Catalogs.CatalogType
{
    /// <summary>
    /// 程序集目录配置。
    /// </summary>
    public sealed class AssemblyCatalogConfig : CatalogConfigBase
    {
        /// <summary>
        /// 或许程序集信息。
        /// </summary>
        public sealed class GetAssemblyInfo
        {
            #region "Field"

            /// <summary>
            /// 获取程序集的Func字典。
            /// </summary>
            private readonly IDictionary<GetAssemblyMode, Func<string, Assembly>> _getAssemblyFunc;

            private readonly Lazy<Assembly> _assembly;

            #endregion "Field"

            #region "Constructor"

            public GetAssemblyInfo()
            {
                //初始化获取程序集的方法。
                _assembly = new Lazy<Assembly>(() =>
                                                   {
                                                       if (_getAssemblyFunc.ContainsKey(GetAssemblyMode))
                                                       {
                                                           return _getAssemblyFunc[GetAssemblyMode](Parameter);
                                                       }
                                                       throw new NotSupportedException();
                                                   });

                //初始化获取程序集的Func字典。
                _getAssemblyFunc = new Dictionary<GetAssemblyMode, Func<string, Assembly>>
                                       {
                                                { GetAssemblyMode.AssemblyFile, GetAssemblyByAssemblyFile }
                                                ,{ GetAssemblyMode.AssemblyString, GetAssemblyByAssemblyString }
                                            };
            }

            #endregion "Constructor"

            #region "Property"

            /// <summary>
            /// 获取程序集的方式。
            /// </summary>
            public GetAssemblyMode GetAssemblyMode { get; set; }

            /// <summary>
            /// 参数。
            /// </summary>
            public string Parameter { get; set; }

            /// <summary>
            /// 程序集。
            /// </summary>
            public Assembly Assembly
            {
                get
                {
                    return _assembly.Value;
                }
            }

            #endregion "Property"

            #region "Private Method"

            /// <summary>
            /// 根据程序集文件获取程序集。
            /// </summary>
            /// <param name="path">程序集路径。</param>
            /// <returns>程序集。</returns>
            private static Assembly GetAssemblyByAssemblyFile(string path)
            {
                try
                {
                    return Assembly.LoadFile(path);
                }
                catch
                {
                    return null;
                }
            }

            /// <summary>
            /// 根据程序集字符串获取程序集。
            /// </summary>
            /// <param name="assemblyString">程序集字符串。</param>
            /// <returns>程序集。</returns>
            private static Assembly GetAssemblyByAssemblyString(string assemblyString)
            {
                try
                {
                    return Assembly.Load(assemblyString);
                }
                catch
                {
                    return null;
                }
            }

            #endregion "Private Method"
        }

        /// <summary>
        /// 获取程序集模式。
        /// </summary>
        public enum GetAssemblyMode
        {
            /// <summary>
            /// 程序集文件。
            /// </summary>
            AssemblyFile = 0,

            /// <summary>
            /// 程序集字符串。
            /// </summary>
            AssemblyString = 1
        }

        #region "Constructor"

        public AssemblyCatalogConfig()
        {
            GetAssemblyInfos = new List<GetAssemblyInfo>();
        }

        #endregion "Constructor"

        #region "Field"

        private IList<Assembly> _composablePart;

        #endregion "Field"

        #region "Property"

        /// <summary>
        /// 获取程序集信息的集合。
        /// </summary>
        [XmlArray("Assemblys")]
        [XmlArrayItem("Assembly")]
        public List<GetAssemblyInfo> GetAssemblyInfos { get; set; }

        #endregion "Property"

        #region "CatalogConfigBase Member"

        /// <summary>
        /// 目录类型。
        /// </summary>
        public override CatalogType CatalogType
        {
            get { return CatalogType.AssemblyCatalog; }
        }

        /// <summary>
        /// 组合部件目录。
        /// </summary>
        [XmlIgnore]
        public override object ComposablePart
        {
            get
            {
                if (_composablePart != null)
                {
                    return _composablePart;
                }
                _composablePart = new List<Assembly>();
                if (!Is.Empty(GetAssemblyInfos))
                {
                    foreach (var getAssemblyInfo in GetAssemblyInfos)
                    {
                        var assembly = getAssemblyInfo.Assembly;
                        if (assembly != null)
                        {
                            _composablePart.Add(getAssemblyInfo.Assembly);
                        }
                    }
                }
                return _composablePart;
            }
        }

        #endregion "CatalogConfigBase Member"
    }
}